package template

import (
	"context"
	"gitee.com/lailonghui/vehicle-supervision-framework/pkg/ferror"
	"gitee.com/shiqiyue/xd-bi/internal/modules/cr/model"
	"github.com/dgryski/trifles/uuid"
	"go.uber.org/zap/buffer"
	"sync"
	"text/template"
)

var sqlCache *sync.Map = &sync.Map{}

var countSqlCache *sync.Map = &sync.Map{}

type cacheItem struct {
	sqlReport *model.SqlReport
	t         *template.Template
}

// 执行sql模板
func ExecuteSqlTemplate(ctx context.Context, sqlReport *model.SqlReport, params map[string]interface{}) (string, error) {
	return executeTemplate(ctx, sqlReport.Sql, sqlReport, params, sqlCache)
}

// 执行countsql模板
func ExecuteCountSqlTemplate(ctx context.Context, sqlReport *model.SqlReport, params map[string]interface{}) (string, error) {
	return executeTemplate(ctx, sqlReport.CountSql, sqlReport, params, countSqlCache)
}

func executeTemplate(ctx context.Context, sql string, sqlReport *model.SqlReport, params map[string]interface{}, cache *sync.Map) (string, error) {
	t := getFromCache(ctx, sqlReport, cache)
	if t == nil {
		t2, err := template.New(uuid.UUIDv4()).Parse(sql)
		if err != nil {
			return "", err
		}
		if t2 == nil {
			return "", ferror.New("template create fail")
		}
		t = t2
		setToCache(ctx, sqlReport, t, cache)
	}
	bs := buffer.Buffer{}
	err := t.Execute(&bs, params)
	if err != nil {
		return "", ferror.Wrap("执行模板异常", err)
	}
	return bs.String(), nil
}

func getFromCache(ctx context.Context, sqlReport *model.SqlReport, cache *sync.Map) *template.Template {
	cacheValue, ok := cache.Load(sqlReport.SqlReportId)
	if ok {
		t, tOk := cacheValue.(*cacheItem)
		if tOk {
			if t.sqlReport.UpdatedAt == sqlReport.UpdatedAt {
				return t.t
			} else {
				cache.Delete(sqlReport.SqlReportId)
			}
		}
	}
	return nil
}

func setToCache(ctx context.Context, sqlReport *model.SqlReport, t *template.Template, cache *sync.Map) {
	cache.Store(sqlReport.SqlReportId, &cacheItem{
		sqlReport: sqlReport,
		t:         t,
	})

}
